/**
 * 轻量级的路由拦截，如需更强大的路由拦截 https://ext.dcloud.net.cn/plugin?id=578
 */
const navigateTo = uni.navigateTo;
const redirectTo = uni.redirectTo;
const reLaunch = uni.reLaunch;
const switchTab = uni.switchTab;
// const navigateBack =  uni.navigateBack();


uni.navigateTo = data => main(data, "navigateTo");
uni.redirectTo = data => main(data, "redirectTo");
uni.reLaunch = data => main(data, "reLaunch");
uni.switchTab = data => main(data, "switchTab"); //小程序点击底部 Tabbar 事件拦截不到

var isFirstPage = true; //是否为第一个打开的页面，如果不需要用拦截启动时打开的第一个页面，可以设置为 false

/**
 * @function Interceptor
 * @param data
 * @param method
 * @param page
 * @param dist
 * @param chain
 *
 * @return {void}
 */

/**
 * 是否登录
 * @return {Promise}
 */
function isLogin() {
  return new Promise((resolve, reject) => {
    if (uni.req.getToken()) {
      uni.req.getUserInfoCacheCheckMobile().then(res => {
        resolve();
      })
    } else {
      reject()
    }
  })
}

/**
 * 登录拦截器
 * @extends Interceptor
 */
function login(data, method, page, dist, chain) {
  // let {url} = data;
  // console.log(url + "页面拦截登录")
  isLogin().then(_ => {
    // console.log(url + "已通过")
    return chain.next(data, method, page, dist);
  }).catch(_ => {
    // console.log(url + "未通过")
    uni.showModal({
      title: "立即登录",
      content: "该功能需要登录！",
      success: e => {
        if (e.confirm) uni.core.toLogin(1);
      }
    })
  })
}

/**
 * 拦截器匹配列表
 */
const matchList = {
  // 拦截
  interceptors: {
    "/pages/index/my/**": login
  },
  // 排除
  excludeInterceptors: ['/', '/pages/user/login/**'],
}

/**
 * 判断是否需要拦截，需要则返回拦截器
 * @param {string} url
 * @return {Interceptor[]}
 */
function needIntercept(url) {
  /**
   * @type {Array}
   */
  let arr = null;
  let {excludeInterceptors, interceptors} = matchList
  // 排除
  if (excludeInterceptors.filter(path => matchPath(path, url)).length > 0) return null

  // 包括
  for (let path in interceptors) {
    if (matchPath(path, url)) {
      if (!arr) arr = [];
      arr.push(interceptors[path])
    }
  }
  return arr
}

function matchPath(path, url) {
  if (path.includes("*"))
    return path2Regx(path).test(url);
  else
    return path == url
}

/**
 * 字符串转路径匹配正则
 * @param {string} path
 * @return {RegExp}
 */
function path2Regx(path) {
  let p = path;
  p = p.split("/").join("\\/")
  p = p.split("**").join(".*")
  p = p.split("*").join(".*?")
  return new RegExp(`^${p}`)
}


/**
 * 获取拦截器处理链
 */
function getChain(dist) {
  let index = 0;
  let list = [];
  let toPath = dist.path;

  let interceptors = needIntercept(toPath);
  interceptors && list.push(...interceptors)

  list = Array.from(new Set(list)); //去重

  const chain = {
    /**
     * 进入下一个拦截器，没有下一个拦截器的情况下跳转到目标页面
     */
    next(data, method, page, dist) {
      if (index >= list.length) {
        return chain.to(data, method);
      }
      list[index++](data, method, page, dist, chain);
    },
    /**
     * 跳转到目标页面
     */
    to(data, method) {
      if (method) ({
        navigateTo,
        redirectTo,
        reLaunch,
        switchTab
      })[method](data)
    }
  }
  return chain;
}

/**
 * 路由拦截入口函数
 */
function main(data, method) {
  var pages = getCurrentPages();
  var page = pages[pages.length - 1];
  var distUrl = uni.core.mergeUrl("/" + page.route, data.url); //合并url，拿到目标页面的绝对路径
  var distUrlSplit = uni.core.splitUrl(distUrl);
  var dist = {
    url: distUrl,
    path: distUrlSplit[0],
    query: distUrlSplit[1],
    point: distUrlSplit[2]
  }
  getChain(dist).next(data, method, page, dist);
}

//这里主要用来拦截应用启动时打开的第一个页面，如果不需要可以将 isFirstPage 变量设置为 false
const mixin = {
  onLoad() {
    if (!isFirstPage) return;
    // console.log("路由拦截混入 onLoad", getCurrentPages());

    var pages = getCurrentPages();
    var page = pages[pages.length - 1];

    //进入
    main({
      url: "/" + page.route
    });

    isFirstPage = false;
  },
}


export default {
  mixin
}
